//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI.HtmlControls;
using CommunityServer.Components;
using CommunityServer.Controls;
using CommunityServer.Discussions.Components;
using CA = ComponentArt.Web.UI;

namespace CommunityServer.Discussions.Controls
{
	/// <summary>
	/// Summary description for PostThreadedView.
	/// </summary>
	public class PostThreadedView : TemplatedWebControl 
	{
	    CSContext csContext;
	    ForumPost post;
		Forum forum;
		ForumPermission permission;
		User currentUser;

		bool siteEnableUserPostingAsAnonymous = false;
		bool forumEnableUserPostingAsAnonymous = false;

		public static int MaxPosts = 1000;
		PostSet ThreadPosts;

		#region AJAX

		[AjaxMethod(IncludeControlValuesWithCallBack=false)]
		public string MovePost(int postID, int parentID)
		{
			if (Permissions.ValidatePermissions(forum, Permission.Moderate, currentUser) || currentUser.IsForumAdministrator)
			{
				ForumPost p = Posts.GetPost(postID, currentUser.UserID);
				if (p != null)
				{
					Moderate.UpdatePostParent(p, parentID, currentUser.UserID);
					return ResourceManager.GetString("PostThreadedView_PostMove_Successful");;
				}
				else
					return ResourceManager.GetString("PostThreadedView_PostMove_PostDoesNotExist");
			}
			else
				throw new CSException(CSExceptionType.AccessDenied, "You are not a moderator.  You do not have permission to move posts.");
		}

		#endregion

		#region Control Event Handlers

		protected override void OnInit(EventArgs e) 
		{
			if (SkinName == null)                
				ExternalSkinFileName = "View-PostThreadedView.ascx";
			else 
				ExternalSkinFileName = SkinName;

			this.csContext = CSContext.Current;
			this.currentUser = csContext.User;

			if (!Page.IsPostBack)
				this.post = Posts.GetPost( csContext.PostID, currentUser.UserID, true, true );

			// Are we looking up the forum by forum id or post id
			//
			if (csContext.SectionID > 0) 
			{
				forum = Forums.GetForum(csContext.SectionID, true, true);
			} 
			else if (csContext.PostID > 0) 
			{
				forum = Forums.GetForumByPostID(csContext.PostID, csContext.User.UserID, true );
			}

			if (forum == null) 
			{
				PermissionBase.RedirectOrExcpetion(CSExceptionType.SectionNotFound, csContext.SectionID.ToString());
			}
			else
			{
				siteEnableUserPostingAsAnonymous = ForumConfiguration.Instance().EnableUserPostingAsAnonymous;
				forumEnableUserPostingAsAnonymous = forum.EnableAnonymousPostingForUsers;
			}

			permission = forum.ResolvePermission( currentUser ) as ForumPermission;
			if( !permission.Read )
				PermissionBase.RedirectOrExcpetion(CSExceptionType.AccessDenied);

			AjaxManager.Register(this, "PostThreadedViewAJAX");

			base.OnInit(e);
		}

		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad (e);
			DataBind();
		}

		protected override void OnPreRender(EventArgs e)
		{
			base.OnPreRender (e);

			if (!this.Page.IsClientScriptBlockRegistered(this.GetType().FullName))
				this.Page.RegisterClientScriptBlock(this.GetType().FullName, string.Format("<script type=\"text/javascript\" src=\"{0}\"></script>",this.ResolveUrl("~/utility/PostThreadedView.js")));

		    StringBuilder script = new StringBuilder();
			script.Append("<script language=\"javascript\">var ");
			script.Append(this.ClientID);
			script.Append("=new PostThreadedView('");
			script.Append(this.ClientID);
			script.Append("','");
			script.Append(ThreadTree.ClientID);
			script.Append("','");
			script.Append(this.PostContainer.ClientID);
			script.Append("','");
			script.Append(this.PostContextMenu == null ? "" : this.PostContextMenu.ClientID);
			script.Append("','");
			script.Append(ForumUrls.Instance().PostInThreadedView(post.ThreadID, 99999).Replace("99999", "{0}"));
			script.Append("',");
			script.Append(this.post == null ? "-1" : this.post.PostID.ToString());
			script.Append(");</script>");

			this.Page.RegisterStartupScript(this.ClientID, script.ToString());		
		}

		#endregion

		#region Child Controls

	    CA.TreeView ThreadTree;
	    HtmlControl PostContainer;
		IText TooManyPostsMessage;
	    CA.Menu PostContextMenu;

		#endregion

		#region Skin

		protected override void AttachChildControls() 
		{
			ThreadTree = (CA.TreeView) FindControl("ThreadTree");
			PostContainer = (HtmlControl) FindControl("PostContainer");
			TooManyPostsMessage = FindText("TooManyPostsMessage");
			PostContextMenu = (CA.Menu) FindControl("PostContextMenu");
		}

		#endregion

		#region Data Binding

		public override void DataBind()
		{
			EnsureChildControls();
			if (PostContextMenu != null)
			{
				ThreadTree.OnContextMenu = "new Function('treeNode', 'event', '" + this.ClientID + ".ShowContextMenu(treeNode, event);')";

			    CA.MenuItem item = new CA.MenuItem();
				item.Text = ResourceManager.GetString("PostThreadedView_ExpandAllReplies");
				item.ClientSideCommand = "eval('" + this.ClientID + ".ExpandChildNodes();')";
				PostContextMenu.Items.Add(item);

				item = new CA.MenuItem();
				item.Text = ResourceManager.GetString("PostThreadedView_CollapseAllReplies");
				item.ClientSideCommand = "eval('" + this.ClientID + ".CollapseChildNodes();')";
				PostContextMenu.Items.Add(item);
			}

			base.DataBind ();

			PreparePostTable();
			BuildPostTree();

			if (this.post != null)
			{
				PostContainer.Attributes.Add("src", ForumUrls.Instance().PostInThreadedView(this.post.ThreadID, this.post.PostID));
			    CA.TreeViewNode node = ThreadTree.FindNodeById(post.PostID.ToString());
				if (node != null)
				{
					ThreadTree.SelectedNode = node;

					while (node.ParentNode != null)
					{
						node = node.ParentNode;
						node.Expanded = true;
					}
				}
			}
		}

		private void BuildPostTree()
		{
			ThreadTree.Nodes.Clear();
			ThreadTree.ClientSideOnNodeSelect = "new Function('" + this.ClientID + ".PostClick();')";

			if (Permissions.ValidatePermissions(forum, Permission.Moderate, currentUser) || currentUser.IsForumAdministrator)
			{
				ThreadTree.DragAndDropEnabled = true;
				ThreadTree.ClientSideOnNodeMove = "new Function('sourceNode', 'targetNode', 'return " + this.ClientID + ".MovePost(sourceNode, targetNode);')";
			}

			BuildPostTree(ThreadTree.Nodes, 0);
		}

		private void BuildPostTree(CA.TreeViewNodeCollection nodes, int parentID)
		{
		    ArrayList posts = ThreadPosts.GetPostsByParent(parentID);
			if (posts.Count == 0)
				return;

		    CA.TreeViewNode node;
			foreach (ForumPost p in posts)
			{
				node = new CA.TreeViewNode();
				node.Value = p.PostID.ToString();
				node.ID = p.PostID.ToString();
				node.Expanded = parentID == 0;

				node.Text = p.Subject;
				if (node.Text.Length > 30)
					node.Text = node.Text.Substring(0, 27) + "...";

				node.Text += "(";
				
				if (p.PostShouldBeIgnored)
					node.Text += ResourceManager.GetString("IgnoredPost_Username");
				else if (p.IsAnonymousPost && siteEnableUserPostingAsAnonymous && forumEnableUserPostingAsAnonymous)
					node.Text += ResourceManager.GetString("DefaultAnonymousUsername");
				else
					node.Text += p.User.DisplayName;

				node.Text += ")";

				if (ThreadPosts.GetPostsByParent(p.PostID).Count > 0)
				{
						BuildPostTree(node.Nodes, p.PostID);
				}

				nodes.Add(node);
			}
		}

		#region Helper Methods

		public void PreparePostTable()
		{
			if (ThreadPosts == null)
			{
				ThreadPosts = Posts.GetPosts(csContext.PostID, 0, MaxPosts, 0, (int) SortOrder.Ascending);

				ArrayList posts = ThreadPosts.GetPostsByParent(0);
				if (posts.Count == 0 || !((Post) posts[0]).IsApproved)
					throw new CSException(CSExceptionType.PostNotFound, "The post could not be found or is not approved");

				if (ThreadPosts.TotalRecords > MaxPosts)
				{
					TooManyPostsMessage.Text = string.Format(ResourceManager.GetString("PostThreadedView_TooManyMessages"), ThreadPosts.TotalRecords, MaxPosts);
					TooManyPostsMessage.Visible = true;
				}

			}
		}

		#endregion

		#endregion

		#region Static Properties/Methods

		public static string ValidTopWindowUrlPattern
		{
			get
			{
				return Regex.Escape(SiteUrls.Instance().Post(99999)).Replace("99999", "[0-9]*?");
			}
		}

		public static string ValidPostWindowUrlPattern
		{
			get
			{
				return Regex.Escape(ForumUrls.Instance().PostInThreadedView(99999, 99999)).Replace("99999", "[0-9]*?");
			}
		}

		#endregion
	}
}
